package com.modulemanager.models

import android.content.Context
import android.graphics.drawable.Drawable
import android.view.Gravity
import androidx.appcompat.content.res.AppCompatResources
import com.libbase.Wrapper
import com.libbase.cast
import com.libui.navigatonbar.MenuData
import com.libui.utils.ColorUtils
import io.reactivex.rxjava3.subjects.BehaviorSubject
import io.reactivex.rxjava3.subjects.PublishSubject

class PageConfig(
    private val name: String? = null,
    private val nameResId: Int? = null,
    title: String? = null,
    subTitle: String? = null,
    var titleAlignment: TitleAlignment = TitleAlignment.CENTER,
    private var icon: Drawable? = null,
    private val iconResId: Int? = null,
    private var selectedIcon: Drawable? = null,
    private val selectedIconResId: Int? = null,
    statusBarType: StatusBarType = StatusBarType.LIGHT,
    navigationBarStyle: NavigationBarStyle = NavigationBarStyle(
        NavigationBarStyle.NavigationBarType.HIDE,
        null,
        null
    ),
    rightMenus: List<MenuData>? = null,
    val transitionType: String?
) {
    enum class StatusBarType(val value: String) {
        LIGHT("light"), DARK("dark");

        companion object {
            fun fromValue(value: String): StatusBarType? =
                values().firstOrNull { it.value == value }
        }
    }

    enum class TitleAlignment(val value: String) {
        LEFT("left"), CENTER("center"), RIGHT("right");

        companion object {
            fun fromValue(value: String): TitleAlignment? =
                values().firstOrNull { it.value == value }
        }

        val gravity: Int
            get() = when (this) {
                LEFT -> Gravity.START or Gravity.CENTER_VERTICAL
                CENTER -> Gravity.CENTER
                RIGHT -> Gravity.END or Gravity.CENTER_VERTICAL
            }
    }

    var title: String? = title
        private set

    var subTitle: String? = subTitle
        private set

    val titleObservable: PublishSubject<Pair<String?, String?>> = PublishSubject.create()

    val navigationBarStyle =
        BehaviorSubject.createDefault(navigationBarStyle)

    val rightMenus =
        BehaviorSubject.createDefault(Wrapper(rightMenus))

    val statusBarType = BehaviorSubject.createDefault(statusBarType)

    class Builder {
        private var name: String? = null
        private var nameResId: Int? = null
        private var title: String? = null
        private var subTitle: String? = null
        private var titleAlignment: TitleAlignment = TitleAlignment.CENTER
        private var icon: Drawable? = null
        private var iconResId: Int? = null
        private var selectedIcon: Drawable? = null
        private var selectedIconResId: Int? = null
        private var rightMenus: List<MenuData>? = null
        private var statusBarType: StatusBarType = StatusBarType.LIGHT
        private var navigationBarStyle: NavigationBarStyle =
            NavigationBarStyle(NavigationBarStyle.NavigationBarType.HIDE, null, null)
        private var transitionType: String? = null

        fun setValues(map: Map<String, Any>): Builder {
            val title = map["title"] as? String
            if (title != null) {
                this.title = title
            }

            val subTitle = map["subTitle"] as? String
            if (subTitle != null) {
                this.subTitle = subTitle
            }

            val titleAlignment: TitleAlignment? = (map["titleAlignment"] as? String)?.let {
                TitleAlignment.fromValue(it)
            }
            if (titleAlignment != null) {
                this.titleAlignment = titleAlignment
            }

            val statusBarType: StatusBarType? = (map["statusBarType"] as? String)?.let {
                StatusBarType.fromValue(it)
            }
            if (statusBarType != null) {
                this.statusBarType = statusBarType
            }

            val navigationBarBGColor =
                (map["navigationBarBGColor"] as? String)?.let { ColorUtils.toColor(it) }
            val navigationBarTintColor =
                (map["navigationBarTintColor"] as? String)?.let { ColorUtils.toColor(it) }

            val navigationBarType: NavigationBarStyle.NavigationBarType? =
                (map["navigationBarType"] as? String)?.let {
                    NavigationBarStyle.NavigationBarType.fromValue(it)
                }
            if (navigationBarType != null) {
                this.navigationBarStyle = NavigationBarStyle(
                    navigationBarType,
                    navigationBarBGColor,
                    navigationBarBGColor
                )
            } else {
                this.navigationBarStyle.backgroundColor = navigationBarBGColor
                this.navigationBarStyle.tintColor = navigationBarTintColor
            }

            val rightMenus: List<MenuData>? =
                cast<List<Map<String, Any>>>(map["rightMenus"])?.let { rightMenusData ->
                    rightMenusData.map { MenuData.create(it) }
                }
            this.rightMenus = rightMenus

            return this
        }

        fun setName(name: String): Builder {
            this.name = name
            return this
        }

        fun setNameResId(nameResId: Int): Builder {
            this.nameResId = nameResId
            return this
        }

        fun setTitle(title: String?): Builder {
            this.title = title
            return this
        }

        fun setSubTitle(subTitle: String?): Builder {
            this.subTitle = subTitle
            return this
        }

        fun setTitleAlignment(titleAlignment: TitleAlignment): Builder {
            this.titleAlignment = titleAlignment
            return this
        }

        fun setIcon(icon: Drawable?): Builder {
            this.icon = icon
            return this
        }

        fun setIconResId(iconResId: Int?): Builder {
            this.iconResId = iconResId
            return this
        }

        fun setSelectedIcon(icon: Drawable?): Builder {
            this.selectedIcon = icon
            return this
        }

        fun setSelectedIconResId(iconResId: Int?): Builder {
            this.selectedIconResId = iconResId
            return this
        }

        fun setRightMenus(menus: List<MenuData>?): Builder {
            this.rightMenus = menus
            return this
        }

        fun setStatusBarType(statusBarType: StatusBarType): Builder {
            this.statusBarType = statusBarType
            return this
        }

        fun setNavigationBarStyle(navigationBarStyle: NavigationBarStyle): Builder {
            this.navigationBarStyle = navigationBarStyle.copy()
            return this
        }

        fun setNavigationBarType(type: NavigationBarStyle.NavigationBarType): Builder {
            navigationBarStyle.type = type
            return this
        }

        fun setTransitionType(transitionType: String?): Builder {
            this.transitionType = transitionType
            return this
        }

        fun create(): PageConfig {
            return PageConfig(
                name = name,
                nameResId = nameResId,
                title = title,
                subTitle = subTitle,
                titleAlignment = titleAlignment,
                icon = icon,
                iconResId = iconResId,
                selectedIcon = selectedIcon,
                selectedIconResId = selectedIconResId,
                statusBarType = statusBarType,
                navigationBarStyle = navigationBarStyle,
                rightMenus = rightMenus,
                transitionType = transitionType
            )
        }
    }

    fun setValues(map: Map<String, Any>) {
        if (map.contains("title") && map.contains("subTitle")) {
            setTitle(map["title"] as? String, map["subTitle"] as? String)
        } else if (map.contains("title")) {
            setTitle(map["title"] as? String)
        } else if (map.contains("subTitle")) {
            setSubTitle(map["subTitle"] as? String)
        }

        val titleAlignment: TitleAlignment? = (map["titleAlignment"] as? String)?.let {
            TitleAlignment.fromValue(it)
        }
        if (titleAlignment != null) {
            this.titleAlignment = titleAlignment
        }

        val statusBarType: StatusBarType? = (map["statusBarType"] as? String)?.let {
            StatusBarType.fromValue(it)
        }
        if (statusBarType != null) {
            this.statusBarType.onNext(statusBarType)
        }

        val navigationBarBGColor =
            (map["navigationBarBGColor"] as? String)?.let { ColorUtils.toColor(it) }
        val navigationBarTintColor =
            (map["navigationBarTintColor"] as? String)?.let { ColorUtils.toColor(it) }

        val navigationBarType: NavigationBarStyle.NavigationBarType? =
            (map["navigationBarType"] as? String)?.let {
                NavigationBarStyle.NavigationBarType.fromValue(it)
            }
        if (navigationBarType != null) {
            navigationBarStyle.onNext(
                NavigationBarStyle(
                    navigationBarType,
                    navigationBarBGColor,
                    navigationBarTintColor
                )
            )
        } else if (navigationBarBGColor != null || navigationBarTintColor != null) {
            val navigationBarStyle = NavigationBarStyle(
                this.navigationBarStyle.value?.type ?: NavigationBarStyle.NavigationBarType.OPAQUE,
                navigationBarBGColor,
                navigationBarTintColor
            )

            this.navigationBarStyle.onNext(navigationBarStyle)
        }

        val rightMenus: List<MenuData>? =
            cast<List<Map<String, Any>>>(map["rightMenus"])?.let { rightMenusData ->
                rightMenusData.map { MenuData.create(it) }
            }
        this.rightMenus.onNext(Wrapper(rightMenus))
    }

    fun setTitle(title: String?) {
        this.title = title
        titleObservable.onNext(Pair(this.title, this.subTitle))
    }

    fun setTitle(title: String?, subTitle: String?) {
        this.title = title
        this.subTitle = subTitle
        titleObservable.onNext(Pair(this.title, this.subTitle))
    }

    fun setSubTitle(subTitle: String?) {
        this.subTitle = subTitle
        titleObservable.onNext(Pair(this.title, this.subTitle))
    }

    fun getName(context: Context?): String? {
        if (name != null) {
            return name
        }

        if (nameResId != null && context != null) {
            return context.resources?.getString(nameResId)
        }

        return null
    }

    fun getIcon(context: Context?): Drawable? {
        if (icon != null) {
            return icon
        }

        if (iconResId != null && context != null) {
            return AppCompatResources.getDrawable(context, iconResId)
        }

        return null
    }

    fun getSelectedIcon(context: Context?): Drawable? {
        if (selectedIcon != null) {
            return selectedIcon
        }

        if (selectedIconResId != null && context != null) {
            return AppCompatResources.getDrawable(context, selectedIconResId)
        }

        return null
    }
}